home *** CD-ROM | disk | FTP | other *** search
- #ifdef _MSC_VER
- #include <macos\msvcmac.h>
- #include <string.h>
- #endif
- //----------------------------------------------
- // Global includes
- //----------------------------------------------
-
- #include <Types.h>
- #include <Files.h>
-
- #include "BinHex.h"
-
- //----------------------------------------------
- // Local includes
- //----------------------------------------------
-
- #include <Resources.h>
- #include <Finder.h>
- #include <Errors.h>
- #include <TextUtils.h>
- #include <PLStringFuncs.h>
-
- //----------------------------------------------
- // InputBuffer structure
- //----------------------------------------------
-
- #define cIgnoreChecksums 0
-
- #define cBuffer_Size 16384
-
- typedef struct {
- UInt32 FileOffset;
-
- UInt8 Buffer[cBuffer_Size];
- UInt32 BytesInBuffer;
-
- UInt32 BufferOffset;
- UInt32 BytesAvailable;
- } tInputBuffer;
-
- typedef struct {
- UInt32 FileOffset;
-
- UInt8 Buffer[cBuffer_Size];
- UInt32 BytesInBuffer;
-
- UInt32 BufferOffset;
- UInt32 BytesAvailable;
-
- Boolean TerminatorFound;
-
- UInt8 ConversionTable[256];
-
- int HoldingPhase;
- UInt8 HoldingByte;
- UInt8 PreviousByte;
- Boolean RepeatFlagFound;
- } tBinHexBuffer;
-
- #pragma options align=mac68k
-
- typedef struct {
- Str63 FileName;
-
- OSType FileType;
- OSType FileCreator;
- UInt16 FinderFlags;
- UInt32 DataLength;
- UInt32 ResourceLength;
- } tBinHexFileHeader;
-
- #pragma options align=reset
-
- //----------------------------------------------
- // tBinHexParser
- //----------------------------------------------
-
- typedef enum {
- cValidating_ParserState = 0,
- cHeaderNameLength_ParserState,
- cHeaderName_ParserState,
- cHeaderNamePad_ParserState,
- cHeader_ParserState,
- cHeaderChecksum_ParserState,
- cDataFork_ParserState,
- cDataForkChecksum_ParserState,
- cResourceFork_ParserState,
- cResourceForkChecksum_ParserState,
- cPassThrough_ParserState,
- cDiscard_ParserState
- } tBinHexParserState;
-
- struct tBinHexParser
- {
- tBinHexClientData * fClientData;
- tBinHexParserCallbacks * fCallbacks;
-
- tInputBuffer * fInputBuffer;
- tBinHexBuffer * fBinHexBuffer;
-
- tBinHexParserState fParserState;
-
- tBinHexFileHeader fHeader;
- UInt16 fCalculatedChecksum;
- UInt16 fActualChecksum;
-
- long fByteCount; // Meaning is state-dependent:
- // cValidating_ParserState: # bytes of header accumulated
- // cDataFork_ParserState: # bytes of data fork remaining
- // cDataGap_ParserState: # bytes of data gap remaining
- // cResourceFork_ParserState: # bytes of resource fork remaining
- // cResourceGap_ParserState: # bytes of resource gap remaining
- // cPassThrough_ParserState: no meaning
- // cDiscard_ParserState: no meaning
- };
-
- //----------------------------------------------
- // Local prototypes
- //----------------------------------------------
-
- static OSErr SkipReturn(tInputBuffer *pBuffer);
- static OSErr ReadFileToReturn(tInputBuffer *pBuffer, Boolean pKeepSpaces, void *pData, long pMaxLength, long *rActualLength);
- static OSErr ReadOneCharacter(tInputBuffer *pBuffer, char *rCharacter);
- static OSErr FindBinHexHeader(tInputBuffer *pBuffer);
-
- static Boolean BinHexBuffer_New(tBinHexBuffer **rBuffer);
- static void BinHexBuffer_Dispose(tBinHexBuffer *pBuffer);
- static OSErr BinHexBuffer_LoadFromFile(tBinHexBuffer *pBuffer, tInputBuffer *pInputBuffer, short pFileRef);
- static Boolean BinHexBuffer_Stuff(tBinHexBuffer *pBuffer, UInt8 *pData, UInt32 pNumberOfBytes, UInt32 *rBytesStuffed);
- static OSErr BinHexBuffer_ReadByte(tBinHexBuffer *pBuffer, UInt8 *rByte, UInt16 *rChecksum);
- static OSErr BinHexBuffer_ReadBytes(tBinHexBuffer *pBuffer, UInt8 *pReadBuffer, UInt32 pNumberOfBytes, UInt16 *rChecksum);
-
- static void AddByteToBinHexChecksum(UInt8 pValue, UInt16 *rChecksum);
- static void AddBytesToBinHexChecksum(UInt8 *pValues, UInt32 pNumberOfBytes, UInt16 *rChecksum);
-
- static OSErr GetBinHexFileHeader(tBinHexBuffer *pBuffer, Boolean *rHeaderIsValid, tBinHexFileHeader *rHeader);
- static Boolean CopyBinHexToFile(tBinHexBuffer *pBuffer, tInputBuffer *pInputBuffer, short pSourceFileRef, short pDestFileRef, UInt32 pNumberOfBytes, UInt16 *rChecksum);
-
- // InputBuffer
-
- static Boolean InputBuffer_New(tInputBuffer **rBuffer);
- static void InputBuffer_Dispose(tInputBuffer *pBuffer);
-
- static OSErr InputBuffer_LoadFromFile(tInputBuffer *pBuffer, short pFileRef);
- static long InputBuffer_Stuff(tInputBuffer *pInputBuffer, void *pData, long pNumberOfBytes);
- static void InputBuffer_DeleteOldData(tInputBuffer *pInputBuffer);
- static void InputBuffer_GetPointer(tInputBuffer *pInputBuffer, void **rData, long *rMaxNumberOfBytes);
- static void InputBuffer_BytesAdded(tInputBuffer *pInputBuffer, long pNumberOfBytes);
-
- // BinHexParser
-
- static Boolean BinHexParser_WriteDecodedData(tBinHexParser *pParser, void *pData, long pDataLength);
-
- //----------------------------------------------
- // Global functions
- //----------------------------------------------
-
- Boolean UnpackBinHexFile(FSSpec *pSourceFile, FSSpec *pDestFile, FSSpec *rDestFile)
- {
- OSErr vErr;
- short vSourceFileRef;
- tInputBuffer * vInputBuffer;
- tBinHexBuffer * vBinHexBuffer;
- FSSpec vDestFile;
- short vDestFileRef;
- tBinHexFileHeader vHeader;
- UInt16 vCalculatedChecksum;
- UInt16 vFileChecksum;
- FInfo vFinderInfo;
- Boolean vHeaderIsValid;
-
- // Open the source file
-
- vErr = FSpOpenDF(pSourceFile, fsRdPerm, &vSourceFileRef);
- if (vErr != noErr) return false;
-
- if (!InputBuffer_New(&vInputBuffer))
- goto errorExit;
-
- if (!BinHexBuffer_New(&vBinHexBuffer))
- goto errorExit2;
-
- // Search for the BinHex header
-
- vErr = InputBuffer_LoadFromFile(vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit3;
-
- vErr = FindBinHexHeader(vInputBuffer);
- if (vErr != noErr) goto errorExit3;
-
- // Read the header
-
- vErr = BinHexBuffer_LoadFromFile(vBinHexBuffer, vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit3;
-
- vErr = GetBinHexFileHeader(vBinHexBuffer, &vHeaderIsValid, &vHeader);
- if (vErr != noErr) goto errorExit3;
- if (!vHeaderIsValid) goto errorExit3;
-
- // Create the destination FSSpec
-
- if (pDestFile != nil)
- vDestFile = *pDestFile;
- else {
- vDestFile = *pSourceFile;
- PLstrcpy(vDestFile.name, vHeader.FileName);
- }
-
- // Create the destination file
-
- FSpDelete(&vDestFile);
-
- vErr = FSpCreate(&vDestFile, vHeader.FileCreator, vHeader.FileType, 0);
- if (vErr != noErr) goto errorExit3;
-
- // Set the finder flags
-
- vErr = FSpGetFInfo(&vDestFile, &vFinderInfo);
- if (vErr != noErr) goto errorExit4;
-
- vFinderInfo.fdFlags = vHeader.FinderFlags & ~(kIsInvisible | kHasBeenInited | kIsOnDesk);
-
- vErr = FSpSetFInfo(&vDestFile, &vFinderInfo);
- if (vErr != noErr) goto errorExit4;
-
- // Open the data fork
-
- vErr = FSpOpenDF(&vDestFile, fsRdWrPerm, &vDestFileRef);
- if (vErr != noErr) goto errorExit4;
-
- // Copy the data fork
-
- vCalculatedChecksum = 0;
- if (!CopyBinHexToFile(vBinHexBuffer, vInputBuffer, vSourceFileRef, vDestFileRef, vHeader.DataLength, &vCalculatedChecksum))
- goto errorExit5;
-
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
-
- if (vBinHexBuffer->BytesAvailable < sizeof(UInt16)) {
- vErr = BinHexBuffer_LoadFromFile(vBinHexBuffer, vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit5;
- }
-
- vErr = BinHexBuffer_ReadBytes(vBinHexBuffer, (UInt8 *)&vFileChecksum, sizeof(UInt16), nil);
- if (vErr != noErr) goto errorExit5;
-
- #if !cIgnoreChecksums
- if (vCalculatedChecksum != vFileChecksum)
- goto errorExit5;
- #endif
-
- // Close the data fork
-
- FSClose(vDestFileRef);
-
- // Open the resource fork
-
- vErr = FSpOpenRF(&vDestFile, fsRdWrPerm, &vDestFileRef);
- if (vErr != noErr) goto errorExit4;
-
- // Copy the resource fork
-
- vCalculatedChecksum = 0;
- if (!CopyBinHexToFile(vBinHexBuffer, vInputBuffer, vSourceFileRef, vDestFileRef, vHeader.ResourceLength, &vCalculatedChecksum))
- goto errorExit5;
-
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
-
- if (vBinHexBuffer->BytesAvailable < sizeof(UInt16)) {
- vErr = BinHexBuffer_LoadFromFile(vBinHexBuffer, vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit5;
- }
-
- vErr = BinHexBuffer_ReadBytes(vBinHexBuffer, (UInt8 *)&vFileChecksum, sizeof(UInt16), nil);
- if (vErr != noErr) goto errorExit5;
-
- #if !cIgnoreChecksums
- if (vCalculatedChecksum != vFileChecksum)
- goto errorExit5;
- #endif
-
- // Close the resource fork
-
- FSClose(vDestFileRef);
-
- // Close the source file
-
- BinHexBuffer_Dispose(vBinHexBuffer);
- InputBuffer_Dispose(vInputBuffer);
- FSClose(vSourceFileRef);
-
- if (rDestFile != nil)
- *rDestFile = vDestFile;
-
- return true;
-
- errorExit5:
- FSClose(vDestFileRef);
-
- errorExit4:
- FSpDelete(&vDestFile);
-
- errorExit3:
- BinHexBuffer_Dispose(vBinHexBuffer);
-
- errorExit2:
- InputBuffer_Dispose(vInputBuffer);
-
- errorExit:
- FSClose(vSourceFileRef);
-
- return false;
- }
-
- Boolean IsBinHexFile(FSSpec *pSourceFile, FSSpec *rDestFile)
- {
- OSErr vErr;
- short vSourceFileRef;
- tInputBuffer * vInputBuffer;
- tBinHexBuffer * vBinHexBuffer;
- FSSpec vDestFile;
- tBinHexFileHeader vHeader;
- Boolean vHeaderIsValid;
-
- // Open the source file
-
- vErr = FSpOpenDF(pSourceFile, fsRdPerm, &vSourceFileRef);
- if (vErr != noErr) return false;
-
- if (!InputBuffer_New(&vInputBuffer))
- goto errorExit;
-
- if (!BinHexBuffer_New(&vBinHexBuffer))
- goto errorExit2;
-
- // Search for the BinHex header
-
- vErr = InputBuffer_LoadFromFile(vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit3;
-
- vErr = FindBinHexHeader(vInputBuffer);
- if (vErr != noErr) goto errorExit3;
-
- // Read the header
-
- vErr = BinHexBuffer_LoadFromFile(vBinHexBuffer, vInputBuffer, vSourceFileRef);
- if (vErr != noErr) goto errorExit3;
-
- vErr = GetBinHexFileHeader(vBinHexBuffer, &vHeaderIsValid, &vHeader);
- if (vErr != noErr) goto errorExit3;
- if (!vHeaderIsValid) goto errorExit3;
-
- // Create the destination FSSpec
-
- vDestFile = *pSourceFile;
- PLstrcpy(vDestFile.name, vHeader.FileName);
-
- // Close the source file
-
- BinHexBuffer_Dispose(vBinHexBuffer);
- InputBuffer_Dispose(vInputBuffer);
- FSClose(vSourceFileRef);
-
- // Return
-
- if (rDestFile != nil)
- *rDestFile = vDestFile;
-
- return true;
-
- errorExit3:
- BinHexBuffer_Dispose(vBinHexBuffer);
-
- errorExit2:
- InputBuffer_Dispose(vInputBuffer);
-
- errorExit:
- FSClose(vSourceFileRef);
-
- return false;
- }
-
- //----------------------------------------------
- // Local functions
- //----------------------------------------------
-
- static OSErr SkipReturn(tInputBuffer *pBuffer)
- {
- OSErr vErr;
-
- vErr = noErr;
-
- do {
- UInt32 vIndex;
- UInt8 * vBufferData;
-
- if (pBuffer->BytesAvailable == 0)
- vErr = eofErr;
-
- vBufferData = &pBuffer->Buffer[pBuffer->BufferOffset];
-
- for (vIndex = 0; vIndex < pBuffer->BytesAvailable; vIndex++) {
- switch (*vBufferData) {
- case 0x09:
- case 0x0d:
- case 0x0a:
- case ' ':
- break;
-
- default:
- pBuffer->BufferOffset += vIndex;
- pBuffer->BytesAvailable -= vIndex;
-
- return noErr;
- } // switch
-
- vBufferData++;
- } // for
-
- pBuffer->BufferOffset = pBuffer->BytesInBuffer;
- pBuffer->BytesAvailable = 0;
-
- } while (vErr == noErr);
-
- return vErr;
- }
-
- static OSErr ReadFileToReturn(tInputBuffer *pBuffer, Boolean pKeepSpaces, void *pData, long pMaxLength, long *rActualLength)
- {
- OSErr vErr;
- UInt8 * vReadData;
- long vActualLength;
-
- vErr = noErr;
-
- vReadData = (UInt8 *)pData;
- vActualLength = 0;
-
- do {
- UInt32 vIndex;
- UInt8 * vBufferData;
-
- if (pBuffer->BytesAvailable == 0)
- vErr = eofErr;
-
- vBufferData = &pBuffer->Buffer[pBuffer->BufferOffset];
-
- for (vIndex = 0; vIndex < pBuffer->BytesAvailable; vIndex++) {
- switch (*vBufferData) {
- case 0x09:
- case 0x0d:
- case 0x0a:
- case ' ':
-
- if ((*vBufferData != ' ') || (!pKeepSpaces)) {
- pBuffer->BufferOffset += vIndex + 1;
- pBuffer->BytesAvailable -= vIndex + 1;
-
- if (rActualLength != nil)
- *rActualLength = vActualLength;
-
- return noErr;
- }
-
- // Fall through to keep space characters
-
- default:
- *vReadData = *vBufferData;
- vReadData++;
- vActualLength++;
- pMaxLength--;
-
- if (pMaxLength == 0) {
- pBuffer->BufferOffset += vIndex + 1;
- pBuffer->BytesAvailable -= vIndex + 1;
-
- if (rActualLength != nil)
- *rActualLength = vActualLength;
-
- return noErr;
- }
-
- break;
- } // switch
-
- vBufferData++;
- } // for
-
- pBuffer->BufferOffset = pBuffer->BytesInBuffer;
- pBuffer->BytesAvailable = 0;
-
- } while (vErr == noErr);
-
- return vErr;
- }
-
- static OSErr ReadOneCharacter(tInputBuffer *pBuffer, char *rCharacter)
- {
- if (pBuffer->BytesAvailable == 0)
- return eofErr;
-
- *rCharacter = pBuffer->Buffer[pBuffer->BufferOffset];
- pBuffer->BufferOffset++;
- pBuffer->BytesAvailable--;
-
- return noErr;
- }
-
- #ifdef _MSC_VER
- char szBinHexFileHeader[40] = "(This file must be converted with BinHex";
- #endif
-
- static OSErr FindBinHexHeader(tInputBuffer *pBuffer)
- {
- Str255 vText;
- OSErr vErr;
- long vActualLength;
- Boolean vFoundString1;
-
- vFoundString1 = false;
-
- do {
- vErr = SkipReturn(pBuffer);
- if (vErr != noErr) return vErr;
-
- vErr = ReadFileToReturn(pBuffer, true, &vText[1], sizeof(vText) - 1, &vActualLength);
- if (vErr != noErr) return vErr;
-
- #ifdef _MSC_VER
- // The MSVC runtimes don't include PLpos, so hopefully this is a
- // reasonable check to see if the file begins with this magic string.
- if (vActualLength >= sizeof(szBinHexFileHeader) &&
- memcmp(szBinHexFileHeader, &vText[1], sizeof(szBinHexFileHeader)) == 0) {
- #else
- vText[0] = vActualLength;
-
- if (PLpos("\p(This file must be converted with BinHex", vText) == 1) {
- #endif
- char vChar;
-
- vErr = SkipReturn(pBuffer);
- if (vErr != noErr) return vErr;
-
- vErr = ReadOneCharacter(pBuffer, &vChar);
- if (vErr != noErr) return vErr;
-
- if (vChar == ':')
- return noErr;
- }
-
- } while (vErr == noErr);
-
- return vErr;
- }
-
- extern short gResFile;
-
- static Boolean BinHexBuffer_New(tBinHexBuffer **rBuffer)
- {
- Handle vConversionTable;
- short curResFile;
-
- if (gResFile == -1) return false;
-
- *rBuffer = (tBinHexBuffer *)NewPtrClear(sizeof(tBinHexBuffer));
- if (MemError() != noErr) return false;
-
- curResFile = CurResFile();
- UseResFile(gResFile);
- vConversionTable = Get1Resource('HQXT', 128);
- BlockMove(*vConversionTable, (**rBuffer).ConversionTable, 256);
- UseResFile(curResFile);
-
- return true;
- }
-
- static void BinHexBuffer_Dispose(tBinHexBuffer *pBuffer)
- {
- DisposePtr((Ptr)pBuffer);
- }
-
- static OSErr BinHexBuffer_LoadFromFile(tBinHexBuffer *pBuffer, tInputBuffer *pInputBuffer, short pFileRef)
- {
- OSErr vErr;
- UInt32 vBytesUsed;
-
- // Load the source buffer
-
- if (pInputBuffer->BytesAvailable == 0) {
- vErr = InputBuffer_LoadFromFile(pInputBuffer, pFileRef);
- if (vErr != noErr) return vErr;
- }
-
- if (!BinHexBuffer_Stuff(pBuffer, &pInputBuffer->Buffer[pInputBuffer->BufferOffset], pInputBuffer->BytesAvailable, &vBytesUsed))
- return paramErr;
-
- pInputBuffer->BufferOffset += vBytesUsed;
- pInputBuffer->BytesAvailable -= vBytesUsed;
-
- return noErr;
- }
-
- static Boolean BinHexBuffer_Stuff(tBinHexBuffer *pBuffer, UInt8 *pData, UInt32 pNumberOfBytes, UInt32 *rBytesStuffed)
- {
- UInt8 * vNextSourceByte;
- int vHoldingPhase;
- int vHoldingByte;
- UInt8 * vNextDestByte;
- int vPreviousByte;
- Boolean vRepeatFlagFound;
- UInt32 vBytesAvailable;
-
- if (pBuffer->BytesInBuffer == pBuffer->BufferOffset) {
- pBuffer->BytesInBuffer = 0;
- pBuffer->BufferOffset = 0;
- }
-
- if (pBuffer->TerminatorFound)
- return pNumberOfBytes;
-
- // Restore our local variables
-
- vNextSourceByte = pData;
- vNextDestByte = &pBuffer->Buffer[pBuffer->BufferOffset];
-
- vHoldingPhase = pBuffer->HoldingPhase;
- vHoldingByte = pBuffer->HoldingByte;
- vPreviousByte = pBuffer->PreviousByte;
- vRepeatFlagFound = pBuffer->RepeatFlagFound;
-
- vBytesAvailable = pNumberOfBytes;
-
- while ((vBytesAvailable > 0)
- && (!pBuffer->TerminatorFound)
- && (pBuffer->BytesInBuffer < cBuffer_Size - 256)) {
- int vByte6;
- int vByte;
-
- vByte6 = pBuffer->ConversionTable[*vNextSourceByte++];
- vBytesAvailable--;
-
- if (vByte6 < 64) {
- switch (vHoldingPhase) {
- case 0:
- vHoldingByte = vByte6 << 2;
- vHoldingPhase = 1;
-
- continue;
-
- case 1:
- vByte = vHoldingByte | (vByte6 >> 4);
-
- vHoldingByte = vByte6 << 4;
- vHoldingPhase = 2;
- break;
-
- case 2:
- vByte = vHoldingByte | (vByte6 >> 2);
-
- vHoldingByte = vByte6 << 6;
- vHoldingPhase = 3;
- break;
-
- case 3:
- vByte = vHoldingByte | vByte6;
-
- vHoldingPhase = 0;
- break;
- } // switch
-
- vByte = vByte & 0x0ff;
-
- if (vRepeatFlagFound) {
- vRepeatFlagFound = false;
-
- if (vByte == 0)
- vByte = 0x90;
- else {
- while (--vByte) {
- *vNextDestByte = vPreviousByte;
- vNextDestByte++;
- pBuffer->BytesInBuffer++;
- } // for
-
- continue;
- }
- }
- else {
- if (vByte == 0x90) {
- vRepeatFlagFound = true;
- continue;
- }
- }
-
- *vNextDestByte++ = vByte;
- pBuffer->BytesInBuffer++;
-
- vPreviousByte = vByte;
- }
- else {
- switch (vByte6) {
- case 0xfd: // whitespace (just ignore)
- break;
-
- case 0xfe:
- pBuffer->TerminatorFound = true;
- break;
-
- case 0xff:
- return false;
- } // switch
- }
-
- } // while
-
- pBuffer->HoldingPhase = vHoldingPhase;
- pBuffer->HoldingByte = vHoldingByte;
- pBuffer->PreviousByte = vPreviousByte;
- pBuffer->RepeatFlagFound = vRepeatFlagFound;
-
- pBuffer->BytesAvailable = pBuffer->BytesInBuffer - pBuffer->BufferOffset;
-
- *rBytesStuffed = pNumberOfBytes - vBytesAvailable;
-
- return true;
- }
-
- static OSErr BinHexBuffer_ReadByte(tBinHexBuffer *pBuffer, UInt8 *rByte, UInt16 *rChecksum)
- {
- if (pBuffer->BytesAvailable == 0)
- return eofErr;
-
- *rByte = pBuffer->Buffer[pBuffer->BufferOffset];
- pBuffer->BufferOffset++;
- pBuffer->BytesAvailable--;
-
- if (rChecksum != nil)
- AddByteToBinHexChecksum(*rByte, rChecksum);
-
- return noErr;
- }
-
- static OSErr BinHexBuffer_ReadBytes(tBinHexBuffer *pBuffer, UInt8 *pReadBuffer, UInt32 pNumberOfBytes, UInt16 *rChecksum)
- {
- if (pNumberOfBytes > pBuffer->BytesAvailable)
- return eofErr;
-
- if (pNumberOfBytes == 0)
- return eofErr;
-
- BlockMove(&pBuffer->Buffer[pBuffer->BufferOffset], pReadBuffer, pNumberOfBytes);
-
- if (rChecksum != nil)
- AddBytesToBinHexChecksum(pReadBuffer, pNumberOfBytes, rChecksum);
-
- pBuffer->BufferOffset += pNumberOfBytes;
- pBuffer->BytesAvailable -= pNumberOfBytes;
-
- return noErr;
- }
-
- static void AddByteToBinHexChecksum(UInt8 pValue, UInt16 *rChecksum)
- {
- SInt32 vChecksum;
- int vIndex;
- SInt32 vSeedValue;
-
- #if cIgnoreChecksums
- return;
- #endif
-
- vChecksum = ((UInt32)*rChecksum << 16) | ((UInt32)pValue << 8);
- vSeedValue = 0x10210000;
-
- vIndex = 8;
- do {
- if (vChecksum < 0)
- vChecksum = (vChecksum << 1) ^ vSeedValue;
- else
- vChecksum = vChecksum << 1;
- } while (--vIndex > 0);
-
- *rChecksum = vChecksum >> 16;
- }
-
- static void AddBytesToBinHexChecksum(UInt8 *pValues, UInt32 pNumberOfBytes, UInt16 *rChecksum)
- {
- #if cIgnoreChecksums
- return;
- #endif
-
- while (pNumberOfBytes > 0) {
- AddByteToBinHexChecksum(*pValues, rChecksum);
- pValues++;
-
- pNumberOfBytes--;
- } // while
- }
-
- static OSErr GetBinHexFileHeader(tBinHexBuffer *pBuffer, Boolean *rHeaderIsValid, tBinHexFileHeader *rHeader)
- {
- UInt16 vCalculatedChecksum;
- UInt8 vTempByte;
- OSErr vErr;
- UInt16 vActualChecksum;
-
- vCalculatedChecksum = 0;
-
- *rHeaderIsValid = false;
-
- vErr = BinHexBuffer_ReadByte(pBuffer, &rHeader->FileName[0], &vCalculatedChecksum);
- if (vErr != noErr) return vErr;
-
- vErr = BinHexBuffer_ReadBytes(pBuffer, &rHeader->FileName[1], rHeader->FileName[0], &vCalculatedChecksum);
- if (vErr != noErr) return vErr;
-
- vErr = BinHexBuffer_ReadByte(pBuffer, &vTempByte, &vCalculatedChecksum);
- if (vErr != noErr) return vErr;
-
- if (vTempByte != 0) return vErr;
-
- vErr = BinHexBuffer_ReadBytes(pBuffer, (UInt8 *)&rHeader->FileType, sizeof(tBinHexFileHeader) - sizeof(Str63), &vCalculatedChecksum);
- if (vErr != noErr) return vErr;
-
- vErr = BinHexBuffer_ReadBytes(pBuffer, (UInt8 *)&vActualChecksum, sizeof(short), nil);
- if (vErr != noErr) return vErr;
-
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
- AddByteToBinHexChecksum(0, &vCalculatedChecksum);
-
- #if cIgnoreChecksums
- *rHeaderIsValid = true;
- #else
- *rHeaderIsValid = (vActualChecksum == vCalculatedChecksum);
- #endif
- return noErr;
- }
-
- static Boolean CopyBinHexToFile(tBinHexBuffer *pBuffer, tInputBuffer *pInputBuffer, short pSourceFileRef, short pDestFileRef, UInt32 pNumberOfBytes, UInt16 *rChecksum)
- {
- OSErr vErr;
-
- while (pNumberOfBytes > 0) {
- long vNumberOfBytes;
-
- if (pBuffer->BytesAvailable == 0) {
- vErr = BinHexBuffer_LoadFromFile(pBuffer, pInputBuffer, pSourceFileRef);
- if (vErr != noErr) return false;;
- } // if
-
- if (pNumberOfBytes > pBuffer->BytesAvailable)
- vNumberOfBytes = pBuffer->BytesAvailable;
- else
- vNumberOfBytes = pNumberOfBytes;
-
- vErr = FSWrite(pDestFileRef, &vNumberOfBytes, &pBuffer->Buffer[pBuffer->BufferOffset]);
- if (vErr != noErr) return false;;
-
- if (rChecksum != nil)
- AddBytesToBinHexChecksum(&pBuffer->Buffer[pBuffer->BufferOffset], vNumberOfBytes, rChecksum);
-
- pNumberOfBytes -= vNumberOfBytes;
-
- pBuffer->BufferOffset += vNumberOfBytes;
- pBuffer->BytesAvailable -= vNumberOfBytes;
- } // while
-
- return true;
- }
-
- //----------------------------------------------
- // InputBuffer
- //----------------------------------------------
-
- static Boolean InputBuffer_New(tInputBuffer **rBuffer)
- {
- *rBuffer = (tInputBuffer *)NewPtrClear(sizeof(tInputBuffer));
- if (MemError() != noErr) return false;
-
- return true;
- }
-
- static void InputBuffer_Dispose(tInputBuffer *pBuffer)
- {
- DisposePtr((Ptr)pBuffer);
- }
-
- static OSErr InputBuffer_LoadFromFile(tInputBuffer *pBuffer, short pFileRef)
- {
- OSErr vErr;
- void * vBufferData;
- long vMaximumBytes;
- long vFileSize;
- long vNumberOfBytes;
-
- // Get the buffer pointer and maximum size
-
- InputBuffer_GetPointer(pBuffer, &vBufferData, &vMaximumBytes);
-
- // Calculate the number of bytes to read
-
- GetEOF(pFileRef, &vFileSize);
-
- vNumberOfBytes = vFileSize - pBuffer->FileOffset;
- if (vNumberOfBytes == 0)
- return eofErr;
-
- if (vNumberOfBytes > vMaximumBytes)
- vNumberOfBytes = vMaximumBytes;
-
- // Read the data
-
- vErr = SetFPos(pFileRef, fsFromStart, pBuffer->FileOffset);
- if (vErr != noErr) return vErr;
-
- vErr = FSRead(pFileRef, &vNumberOfBytes, vBufferData);
- if (vErr != noErr) return vErr;
-
- // Tell the buffer about the new data
-
- InputBuffer_BytesAdded(pBuffer, vNumberOfBytes);
-
- return noErr;
- }
-
- #ifdef MAC_IE_ONLY
- static long InputBuffer_Stuff(tInputBuffer *pInputBuffer, void *pData, long pNumberOfBytes)
- {
- void * vBufferData;
- long vNumberOfBytes;
-
- InputBuffer_GetPointer(pInputBuffer, &vBufferData, &vNumberOfBytes);
-
- if (vNumberOfBytes > pNumberOfBytes)
- vNumberOfBytes = pNumberOfBytes;
-
- BlockMove(pData, vBufferData, vNumberOfBytes);
-
- InputBuffer_BytesAdded(pInputBuffer, vNumberOfBytes);
-
- return vNumberOfBytes;
- }
-
- static void InputBuffer_DeleteOldData(tInputBuffer *pInputBuffer)
- {
- void * vSourceData;
- long vNumberOfBytes;
-
- vNumberOfBytes = pInputBuffer->BytesInBuffer - pInputBuffer->BufferOffset;
-
- if (vNumberOfBytes == 0) {
- pInputBuffer->BufferOffset = 0;
- pInputBuffer->BytesInBuffer = 0;
- return;
- }
-
- vSourceData = &pInputBuffer->Buffer[pInputBuffer->BufferOffset];
-
- BlockMove(vSourceData, &pInputBuffer->Buffer[0], vNumberOfBytes);
-
- pInputBuffer->BufferOffset = 0;
- pInputBuffer->BytesInBuffer = vNumberOfBytes;
- }
- #endif
-
- static void InputBuffer_GetPointer(tInputBuffer *pInputBuffer, void **rData, long *rMaxNumberOfBytes)
- {
- if (pInputBuffer->BufferOffset == pInputBuffer->BytesInBuffer) {
- pInputBuffer->BufferOffset = 0;
- pInputBuffer->BytesInBuffer = 0;
- }
-
- *rData = &pInputBuffer->Buffer[pInputBuffer->BytesInBuffer];
- *rMaxNumberOfBytes = cBuffer_Size - pInputBuffer->BytesInBuffer;
- }
-
- static void InputBuffer_BytesAdded(tInputBuffer *pInputBuffer, long pNumberOfBytes)
- {
- pInputBuffer->BytesInBuffer += pNumberOfBytes;
- pInputBuffer->BytesAvailable += pNumberOfBytes;
- pInputBuffer->FileOffset += pNumberOfBytes;
- }
-
- #ifdef MAC_IE_ONLY
- //----------------------------------------------
- // BinHex Parser
- //----------------------------------------------
-
- Boolean BinHexParser_New(tBinHexClientData *pClientData, tBinHexParserCallbacks *pCallbacks, tBinHexParser **rParser)
- {
- tBinHexParser * vParser;
-
- vParser = (tBinHexParser *)NewPtr(sizeof(struct tBinHexParser));
- if (MemError() != noErr)
- return false;
-
- vParser->fClientData = pClientData;
- vParser->fCallbacks = pCallbacks;
-
- if (!InputBuffer_New(&vParser->fInputBuffer))
- goto error1;
-
- if (!BinHexBuffer_New(&vParser->fBinHexBuffer))
- goto error2;
-
- vParser->fParserState = cValidating_ParserState;
- vParser->fByteCount = 0;
-
- *rParser = vParser;
-
- return true;
-
- //-------------------
- error2:
- InputBuffer_Dispose(vParser->fInputBuffer);
-
- error1:
- DisposePtr((Ptr)vParser);
- return false;
- }
-
- void BinHexParser_Dispose(tBinHexParser *pParser)
- {
- BinHexParser_Flush(pParser);
-
- BinHexBuffer_Dispose(pParser->fBinHexBuffer);
-
- InputBuffer_Dispose(pParser->fInputBuffer);
-
- DisposePtr((Ptr)pParser);
- }
-
- Boolean BinHexParser_Flush(tBinHexParser *pParser)
- {
- if (pParser->fParserState == cValidating_ParserState) {
-
- pParser->fParserState = cPassThrough_ParserState;
-
- if (pParser->fInputBuffer->BytesInBuffer > 0)
- if (!BinHexParser_WriteData(pParser, pParser->fInputBuffer->Buffer, pParser->fInputBuffer->BytesInBuffer))
- return false;
- } // if
-
- return true;
- }
-
- void BinHexParser_Kill(tBinHexParser *pParser)
- {
- pParser->fParserState = cPassThrough_ParserState;
- }
-
- Boolean BinHexParser_WriteData(tBinHexParser *pParser, void *pData, long pDataLength)
- {
- while (pDataLength > 0) {
-
- switch (pParser->fParserState) {
-
- case cValidating_ParserState: {
- UInt32 vBytesStuffed;
- OSErr vErr;
-
- // Reset the input buffer so that we're searching from the beginning each time (the search code isn't very bright)
-
- pParser->fInputBuffer->BufferOffset = 0;
- pParser->fInputBuffer->BytesAvailable = pParser->fInputBuffer->BytesInBuffer;
-
- // Stuff as much of the new data into the buffer as will fit
-
- vBytesStuffed = InputBuffer_Stuff(pParser->fInputBuffer, pData, pDataLength);
- pData = (UInt8 *)pData + vBytesStuffed;
- pDataLength -= vBytesStuffed;
-
- // See if there's a header in there somewhere
-
- vErr = FindBinHexHeader(pParser->fInputBuffer);
- if (vErr == noErr) {
- // Found the header - start parsing data
-
- InputBuffer_DeleteOldData(pParser->fInputBuffer);
-
- pParser->fParserState = cHeaderNameLength_ParserState;
- pParser->fByteCount = 0;
-
- // Call ourselves recursively to process the remains of the buffer
-
- if ((pParser->fInputBuffer->BytesAvailable > 0)
- && !BinHexParser_WriteData(pParser, pParser->fInputBuffer->Buffer, pParser->fInputBuffer->BytesAvailable))
- return false;
-
- break;
- } // if
-
- if (pParser->fInputBuffer->BytesInBuffer == cBuffer_Size) {
-
- // The buffer's full and we still haven't found the data - switch to pass-through mode
-
- if (!BinHexParser_Flush(pParser))
- return false;
-
- } // if
-
- break;
- }
-
- case cHeaderNameLength_ParserState:
- case cHeaderName_ParserState:
- case cHeaderNamePad_ParserState:
- case cHeader_ParserState:
- case cHeaderChecksum_ParserState:
- case cDataFork_ParserState:
- case cDataForkChecksum_ParserState:
- case cResourceFork_ParserState:
- case cResourceForkChecksum_ParserState: {
- long vBytesStuffed;
-
- if (!BinHexBuffer_Stuff(pParser->fBinHexBuffer, pData, pDataLength, &vBytesStuffed))
- return false;
-
- if ((pParser->fBinHexBuffer->BytesAvailable > 0)
- && !BinHexParser_WriteDecodedData(pParser, &pParser->fBinHexBuffer->Buffer[pParser->fBinHexBuffer->BufferOffset], pParser->fBinHexBuffer->BytesAvailable))
- return false;
-
- pParser->fBinHexBuffer->BufferOffset = pParser->fBinHexBuffer->BytesInBuffer;
- pParser->fBinHexBuffer->BytesAvailable = 0;
-
- pData = (UInt8 *)pData + vBytesStuffed;
- pDataLength -= vBytesStuffed;
-
- break;
- }
-
- case cPassThrough_ParserState:
- if (!pParser->fCallbacks->WriteDF(pParser->fClientData, pData, pDataLength))
- return false;
-
- pDataLength = 0;
- break;
-
- case cDiscard_ParserState:
- pDataLength = 0;
- break;
-
- default:
- DebugStr("\pBinHexParser_WriteData: Illegal switch selector");
- break;
-
- } // switch
-
- } // while
-
- return true;
- }
-
- Boolean BinHexParser_IsBinHex(tBinHexParser *pParser)
- {
- return ((pParser->fParserState != cValidating_ParserState) && (pParser->fParserState != cPassThrough_ParserState));
- }
-
- static Boolean BinHexParser_WriteDecodedData(tBinHexParser *pParser, void *pData, long pDataLength)
- {
- while (pDataLength > 0) {
-
- switch (pParser->fParserState) {
-
- case cHeaderNameLength_ParserState:
-
- pParser->fCalculatedChecksum = 0;
-
- pParser->fByteCount = *(UInt8 *)pData;
- AddByteToBinHexChecksum(pParser->fByteCount, &pParser->fCalculatedChecksum);
-
- pData = (UInt8 *)pData + 1;
- pDataLength -= 1;
-
- pParser->fHeader.FileName[0] = 0; // The length byte will get incremented as the name is read in
-
- pParser->fParserState = cHeaderName_ParserState;
- break;
-
- case cHeaderName_ParserState: {
- long vNumberOfBytes;
-
- vNumberOfBytes = pParser->fByteCount;
- if (vNumberOfBytes > pDataLength)
- vNumberOfBytes = pDataLength;
-
- BlockMove(pData, &pParser->fHeader.FileName[pParser->fHeader.FileName[0] + 1], vNumberOfBytes);
- AddBytesToBinHexChecksum(pData, vNumberOfBytes, &pParser->fCalculatedChecksum);
-
- pParser->fHeader.FileName[0] += vNumberOfBytes;
-
- pData = (UInt8 *)pData + vNumberOfBytes;
- pDataLength -= vNumberOfBytes;
-
- pParser->fByteCount -= vNumberOfBytes;
- if (pParser->fByteCount == 0) {
- pParser->fParserState = cHeaderNamePad_ParserState;
- } // if
-
- break;
- }
-
- case cHeaderNamePad_ParserState:
- if (*(UInt8 *)pData != 0)
- return false;
-
- AddByteToBinHexChecksum(*(UInt8 *)pData, &pParser->fCalculatedChecksum);
-
- pData = (UInt8 *)pData + 1;
- pDataLength -= 1;
-
- pParser->fParserState = cHeader_ParserState;
- pParser->fByteCount = 0;
- break;
-
- case cHeader_ParserState: {
- long vNumberOfBytes;
-
- vNumberOfBytes = (sizeof(tBinHexFileHeader) - sizeof(Str63)) - pParser->fByteCount;
- if (vNumberOfBytes > pDataLength)
- vNumberOfBytes = pDataLength;
-
- BlockMove(pData, (UInt8 *)&pParser->fHeader.FileType + pParser->fByteCount, vNumberOfBytes);
- AddBytesToBinHexChecksum(pData, vNumberOfBytes, &pParser->fCalculatedChecksum);
-
- pParser->fByteCount += vNumberOfBytes;
-
- pData = (UInt8 *)pData + vNumberOfBytes;
- pDataLength -= vNumberOfBytes;
-
- if (pParser->fByteCount == (sizeof(tBinHexFileHeader) - sizeof(Str63))) {
- pParser->fParserState = cHeaderChecksum_ParserState;
- pParser->fByteCount = sizeof(UInt16);
- }
-
- break;
- }
-
- case cHeaderChecksum_ParserState:
- case cDataForkChecksum_ParserState:
- case cResourceForkChecksum_ParserState: {
- tBinHexFileInfo vFileInfo;
-
- // Collect the two bytes for the checksum
-
- if (pDataLength > 1) {
- if (pParser->fByteCount == 1) {
- *((UInt8 *)&pParser->fActualChecksum + 1) = *(UInt8 *)pData;
-
- pData = (UInt8 *)pData + 1;
- pDataLength -= 1;
- }
- else {
- pParser->fActualChecksum = *(UInt16 *)pData;
-
- pData = (UInt8 *)pData + sizeof(UInt16);
- pDataLength -= sizeof(UInt16);
- }
- }
- else {
- *((UInt8 *)&pParser->fActualChecksum) = *(UInt8 *)pData;
-
- pData = (UInt8 *)pData + 1;
- pDataLength -= 1;
-
- pParser->fByteCount -= 1;
- break;
- }
-
- // Include two zero bytes in the calculated checksum
-
- AddByteToBinHexChecksum(0, &pParser->fCalculatedChecksum);
- AddByteToBinHexChecksum(0, &pParser->fCalculatedChecksum);
-
- // Completed the header - verify the checksum
-
- if (pParser->fActualChecksum != pParser->fCalculatedChecksum)
- return false;
-
- switch (pParser->fParserState) {
- case cHeaderChecksum_ParserState: {
- // Send the header to the client
-
- BlockMove(pParser->fHeader.FileName, vFileInfo.fName, sizeof(Str63));
- vFileInfo.fFileType = pParser->fHeader.FileType;
- vFileInfo.fFileCreator = pParser->fHeader.FileCreator;
- vFileInfo.fFinderFlags = pParser->fHeader.FinderFlags;
-
- if (!pParser->fCallbacks->SetFileInfo(pParser->fClientData, &vFileInfo))
- return false;
-
- // Start parsing the data fork
-
- pParser->fParserState = cDataFork_ParserState;
- pParser->fByteCount = pParser->fHeader.DataLength;
- pParser->fCalculatedChecksum = 0;
-
- break;
- }
-
- case cDataForkChecksum_ParserState:
- pParser->fParserState = cResourceFork_ParserState;
- pParser->fByteCount = pParser->fHeader.ResourceLength;
- pParser->fCalculatedChecksum = 0;
- break;
-
- case cResourceForkChecksum_ParserState:
- pParser->fParserState = cDiscard_ParserState;
- pParser->fByteCount = 0;
- break;
- } // switch
-
- break;
- }
-
- case cDataFork_ParserState:
-
- if (pDataLength >= pParser->fByteCount) {
- AddBytesToBinHexChecksum(pData, pParser->fByteCount, &pParser->fCalculatedChecksum);
-
- if (!pParser->fCallbacks->WriteDF(pParser->fClientData, pData, pParser->fByteCount))
- return false;
-
- pData = (void *)((UInt8 *)pData + pParser->fByteCount);
- pDataLength -= pParser->fByteCount;
-
- pParser->fParserState = cDataForkChecksum_ParserState;
- pParser->fByteCount = sizeof(UInt16);
- }
- else {
- AddBytesToBinHexChecksum(pData, pDataLength, &pParser->fCalculatedChecksum);
-
- if (!pParser->fCallbacks->WriteDF(pParser->fClientData, pData, pDataLength))
- return false;
-
- pParser->fByteCount -= pDataLength;
- pDataLength = 0;
- }
-
- break;
-
- case cResourceFork_ParserState:
-
- if (pDataLength >= pParser->fByteCount) {
- AddBytesToBinHexChecksum(pData, pParser->fByteCount, &pParser->fCalculatedChecksum);
-
- if (!pParser->fCallbacks->WriteRF(pParser->fClientData, pData, pParser->fByteCount))
- return false;
-
- pData = (void *)((UInt8 *)pData + pParser->fByteCount);
- pDataLength -= pParser->fByteCount;
-
- pParser->fParserState = cResourceForkChecksum_ParserState;
- pParser->fByteCount = sizeof(UInt16);
- }
- else {
- AddBytesToBinHexChecksum(pData, pDataLength, &pParser->fCalculatedChecksum);
-
- if (!pParser->fCallbacks->WriteRF(pParser->fClientData, pData, pDataLength))
- return false;
-
- pParser->fByteCount -= pDataLength;
- pDataLength = 0;
- }
-
- break;
-
- case cPassThrough_ParserState:
- if (!pParser->fCallbacks->WriteDF(pParser->fClientData, pData, pDataLength))
- return false;
-
- pDataLength = 0;
- break;
-
- case cDiscard_ParserState:
- pDataLength = 0;
- break;
-
- default:
- DebugStr("\pBinHexParser_WriteData: Illegal switch selector");
- break;
-
- } // switch
-
- } // while
-
- return true;
- }
- #endif
-